package net.hn.hnms.sys.common.feign;

import feign.Logger;
import feign.Request;
import feign.RetryableException;
import feign.Retryer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FeignFormatterRegistrar;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.format.FormatterRegistry;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.time.LocalDateTime;

/**
 * FeignClient配置类
 *
 * @author Jiangmf
 * @date 2019-11-22
 */
@Configuration
@Slf4j
public class FeignConfig implements FeignFormatterRegistrar {

    /**
     * 使Feign支持特殊时间格式
     *
     * @param registry
     */
    @Override
    public void registerFormatters(FormatterRegistry registry) {
//        registry.addConverter(LocalDateTime.class, String.class, DateTimeConverter.getLocalDateTimeToString());
    }

    /**
     * 默认Feign log，设为全部
     *
     * @return
     */
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }

    /**
     * 默认超时时间，设为7秒
     *
     * @param env
     * @return
     */
    @Bean
    public static Request.Options requestOptions(ConfigurableEnvironment env) {
        return new Request.Options(7000, 7000);
    }

    /**
     * 自定义重试器，以解决全局异常处理
     *
     * @return
     */
    @Bean
    public Retryer feignRetryer() {

        // 一个无重试，直接进行全局异常处理的重试器
        return new Retryer() {

            @Override
            public void continueOrPropagate(RetryableException e) {
                Throwable cause = e.getCause();
                if (cause != null && SocketTimeoutException.class.isAssignableFrom(cause.getClass())) {
                    throw new RuntimeException("数据访问超时", cause);
                } else if (cause != null && UnknownHostException.class.isAssignableFrom(cause.getClass())) {
                    throw new RuntimeException("数据源地址解析失败，请检查网络连接", cause);
                } else if (cause != null && IOException.class.isAssignableFrom(cause.getClass())) {
                    throw new RuntimeException("数据访问未知IO错误", cause);
                } else {
                    throw new RuntimeException("数据获取失败", cause);
                }
            }

            @Override
            public Retryer clone() {
                return this;
            }
        };
    }
}
